use std::collections::HashMap;

mod flaky;
mod i32range;

fn main() {
    println!("Hello, world!");
    println!("{}", triangle(10));
    println!("{}", triangle2(10));
    println!("{}", triangle3(10));
    println!("{}", triangle(10) == triangle2(10));
    println!("{}", triangle(10) == triangle3(10));
    println!("{}", triangle2(10) == triangle3(10));

    let text = "   ponles    \n     giraffes\niguanas\nsquid".to_string();
    let v = text.lines().map(|s| s.trim()).collect::<Vec<&str>>();
    println!("{:?}", v);
    let con = v.join(" ");
    println!("{}", con);


    println!("{}", factorial(10));
    println!("{}", fibonacci(30));

    println!("{}", factorial(10) == factorial2(10));

    println!("{}", add(1, 2));

    text.lines().map(|s| s.trim()).filter(|s| *s != "iguanas").for_each(|s| println!("{}", s));

    // fitler_map 的用法
    use std::str::FromStr;
    let text = "1\nfrond .25 289\n3.1415 estuary\n";
    for number in text.split_ascii_whitespace().filter_map(|s| f64::from_str(s).ok()) {
        println!("{:4.2}", number.sqrt());
    }

    // flat_map 的用法
    let mut major_cities = HashMap::new();
    major_cities.insert("Japan", vec!["Tokyo", "Kyoto"]);
    major_cities.insert("USA", vec!["New York", "Los Angeles", "Chicago"]);
    major_cities.insert("Canada", vec!["Toronto", "Vancouver", "Montreal"]);
    major_cities.insert("England", vec!["London", "Manchester", "Liverpool"]);
    let countries = ["Japan", "USA", "Canada", "England"];
    for city in countries.iter().flat_map(|cities| &major_cities[cities]) {
        println!("{}", city);
    }

    // flatten 的用法
    let data = vec![vec![1, 2, 3], vec![4, 5, 6], vec![7, 8, 9]];
    let flattened: Vec<i32> = data.into_iter().flatten().collect();
    println!("{:?}", flattened);


    // take and take_while的用法
    let message = "To:jimb\r\n\
    From: supergo <editor@oreilly.com>\r\n\
\r\n\
Did you get any writing done today?\r\n\
When will you stop wasting time plotting fractals?\r\n";
    message.lines().take_while(|l| !l.is_empty()).for_each(|f| println!("{}",f));
    // skip and skip_while的用法
    message.lines().skip_while(|l| !l.is_empty()).for_each(|f| println!("{}",f));

    for body in message.lines().skip_while(|l| !l.is_empty()).skip(1) {
        println!("{}", body);
    }

    let mut chars = "226153980,1766319049".chars().peekable();
    println!("{}", parse_number(&mut chars));
    println!("{}", chars.next().unwrap());
    println!("{}", parse_number(&mut chars));
    println!("{}", chars.next().is_none());

    let mut fla = flaky::Flaky(true);
    println!("{:?}", fla.next());
    println!("{:?}", fla.next());
    println!("{:?}", fla.next());
    println!("{:?}", fla.next());

    let mut fla = flaky::Flaky(true).fuse();
    println!("{:?}", fla.next());
    println!("{:?}", fla.next());
    println!("{:?}", fla.next());
    println!("{:?}", fla.next());

    let v: Vec<_> = (0..).zip("ABCD".chars()).collect();
    println!("{:?}", v);

    use std::iter::repeat;
    let endings = ["once", "twice", "chicken soup with rice"];
    let rhyme:Vec<_> = repeat("going").zip(endings).collect();
    println!("{:?}", rhyme);

    read_number(100);


    let mut populations = HashMap::new();
    populations.insert("Portland", 583_776);
    populations.insert("Fossil", 449);
    populations.insert("Greenhorn", 2);
    populations.insert("Boring", 7762);
    populations.insert("The Dalles", 15340);

    println!("{:?}", populations.iter().max_by_key(|&(_name, pop)| pop));
    println!("{:?}", populations.iter().min_by_key(|&(_name, pop)| pop));


    let mut pi = 0.0;
    let mut numerator = 1.0;

    for k in (i32range::I32Range { start: 0, end: 14 }) {
        pi += numerator / (2 * k + 1) as f64;
        numerator /= -3.0;
    }

    pi *= f64::sqrt(12.0);
    println!("{}", pi);


}

fn triangle(n:i32) -> i32 {
    let mut sum = 0;
    for i in 1..=n {
        sum += i;
    }
    sum
}

fn triangle2(n:i32) -> i32 {
    (1..=n).sum()
}

fn triangle3(n:i32) -> i32 {
    (1..=n).fold(0, |sum, i| sum + i)
}

// 一个计算阶乘的函数
fn factorial(n: i64) -> i64 {
    (1..=n).fold(1, |sum, i| sum * i)
}

fn factorial2(n:i64) -> i64 {
    (1..=n).product()
}

// 一个计算斐波那契数列的函数
fn fibonacci(n: i64) -> i64 {
    (0..n).fold((0, 1), |(a, b), _| (b, a + b)).0
}

// 编写一个泛型的相加函数
fn add<T: std::ops::Add<Output = T>>(a: T, b: T) -> T {
    a + b
}

use std::iter::Peekable;

fn parse_number<I>(tokens: &mut Peekable<I>) ->u32 
    where I: Iterator<Item = char>
    {
        let mut n = 0;
        loop {
            match tokens.peek() {
                Some(r) if r.is_digit(10) => {
                    n = n* 10 + r.to_digit(10).unwrap();
                }
                _=> return n
                
            }
            tokens.next();
        }
    }


// 数数游戏

fn read_number(n:i64) {
    use std::iter::{once, repeat};
    // repeat循环后， take 取个数， 再chain连接  once 一次 后新的迭代器的循环
    let fizzes = repeat("").take(2).chain(once("报3除")).cycle();
    let buzzes = repeat("").take(4).chain(once("报5除")).cycle();
    let fizzes_buzzes = fizzes.zip(buzzes);
    // 这是一个死循环， 因为cycle方法会无限循环
    // ("", "")
// ("", "")
// ("报3除", "")
// ("", "")
//("", "报5除")
    // fizzes_buzzes.clone().for_each(|s| println!("{:?}", s));
    let fizz_buzz = (1..n).zip(fizzes_buzzes).map(|tuple| {
        match tuple {
            (i, ("", "")) => i.to_string(),
            (_, (fizz, buzz)) => format!("{}{}", fizz, buzz),// 此处fizz和 buzz总有一个值不为空串
        }
    });

    for line in fizz_buzz {
        println!("{}", line);
    }
}